package com.brotherly.framework.net;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;

import android.content.Context;
import android.content.SharedPreferences;
import android.net.TrafficStats;
import android.os.Process;
import android.util.Base64;

public class NetworkWatch
{
    public static final String SP_NETWORKWATCH = "SP_NETWORKWATCH";
    public static final int MAX_DAY = 15;

    static Context context = null;

    /*
     * 记录开机到现在 流量信息, 有可能是跨天数据
     */
    static DateItem currentData = null;

    /*
     * 15天的流量
     */
    static DateItem[] datas = null;

    /*
     * 当天的数据
     */
    static DateItem todayData = null;

    /*
     * 当月的数据
     */
    public static DateItem curMonthData = null;

    /**
     * 监控流量
     */
    public static void Watch()
    {
        int uid = Process.myUid();

        // 开机到现在
        long appAll = TrafficStats.getUidRxBytes(uid) + TrafficStats.getUidTxBytes(uid);
        long systemAll = TrafficStats.getTotalRxBytes() + TrafficStats.getTotalTxBytes();
        long systemGprs = TrafficStats.getMobileRxBytes() + TrafficStats.getMobileTxBytes();
        long systemWifi = systemAll - systemGprs;

        if (currentData == null)
        {
            currentData = new DateItem();
            currentData.appAll = appAll;
            currentData.appGprs = 0;
            currentData.appWifi = 0;
            // currentData.systemAll = systemAll;
            // currentData.systemGprs = systemGprs;
            // currentData.systemWifi = systemWifi;
        }

        // 上一次监控到现在
        long appAll_Add = appAll - currentData.appAll;
        long appGprs_Add = 0;
        long appWifi_Add = 0;
        long systemAll_Add = systemAll - currentData.systemAll;
        long systemGprs_Add = systemGprs - currentData.systemGprs;
        long systemWifi_Add = systemWifi - currentData.systemWifi;

        currentData.appAll = appAll;
        currentData.appGprs = 0;
        currentData.appWifi = 0;
        currentData.systemAll = systemAll;
        currentData.systemGprs = systemGprs;
        currentData.systemWifi = systemWifi;

        if (appAll_Add > 0 && systemAll_Add > 0)
        {
            assert (systemAll_Add >= appAll_Add);

            if (systemGprs_Add >= appAll_Add && systemWifi_Add >= appAll_Add)
            {
                appWifi_Add += appAll_Add;
            } else if (systemGprs_Add >= appAll_Add)
            {
                appGprs_Add += appAll_Add;
            } else if (systemWifi_Add >= appAll_Add)
            {
                appWifi_Add += appAll_Add;
            } else
            {
                appGprs_Add += appAll_Add * systemGprs_Add / systemAll_Add;
                appWifi_Add += appAll_Add * systemWifi_Add / systemAll_Add;
            }
        }

        if (todayData == null)
            todayData = todayItem();

        todayData.appAll += appAll_Add;
        todayData.appGprs += appGprs_Add;
        todayData.appWifi += appWifi_Add;
        todayData.systemAll += systemAll_Add;
        todayData.systemGprs += systemGprs_Add;
        todayData.systemWifi += systemWifi_Add;

        todayData = todayItem();

        curMonthData.appAll += appAll_Add;
        curMonthData.appGprs += appGprs_Add;
        curMonthData.appWifi += appWifi_Add;
        curMonthData.systemAll += systemAll_Add;
        curMonthData.systemGprs += systemGprs_Add;
        curMonthData.systemWifi += systemWifi_Add;

        int month = Calendar.getInstance().get(Calendar.MONTH) + (1 - Calendar.JANUARY);
        String monthStr = String.valueOf(month);
        if (!curMonthData.date.equals(monthStr))
        {
            curMonthData = new DateItem();
            curMonthData.date = monthStr;
        }

        if (appAll_Add > 0)
            Save();
    }

    /**
     * 初始化
     */
    public static void Init(Context context)
    {
        NetworkWatch.context = context;

        curMonthData = new DateItem();
        int month = Calendar.getInstance().get(Calendar.MONTH) + (1 - Calendar.JANUARY);
        curMonthData.date = String.valueOf(month);

        datas = new DateItem[MAX_DAY];
        for (int i = 0; i < MAX_DAY; i++)
        {
            Calendar c = Calendar.getInstance();
            c.add(Calendar.DAY_OF_MONTH, -i);

            SimpleDateFormat datesdf = new SimpleDateFormat("M月d日", Locale.getDefault());
            String date = datesdf.format(c.getTime());

            DateItem item = new DateItem();
            item.date = date;

            datas[MAX_DAY - i - 1] = item;
        }

        // SharedPreferences pre = context.getSharedPreferences(
        // WidgetGlobal.SP_NAME, Context.MODE_WORLD_WRITEABLE);
        // String tmpSaveBase64 = pre.getString("NetworkWatch", "");
        // if (tmpSaveBase64 != null && tmpSaveBase64.length() > 0)
        // {
        // byte[] base64Bytes = Base64.decode(tmpSaveBase64.getBytes(),
        // Base64.DEFAULT);
        // ByteArrayInputStream barr = new ByteArrayInputStream(base64Bytes);
        // DataInputStream din = new DataInputStream(barr);
        //
        // curMonthData.Load(din);
        //
        // for (int i = 0; i < datas.length; i++)
        // {
        // datas[i].Load(din);
        // }
        // }

        Watch();
    }

    /**
     * 退出
     */
    public static void Exit()
    {
        Watch();
        Save();
    }

    private static void Save()
    {
        try
        {
            ByteArrayOutputStream barr = new ByteArrayOutputStream();
            DataOutputStream don = new DataOutputStream(barr);

            curMonthData.Save(don);

            for (DateItem item : datas)
            {
                item.Save(don);
            }

            byte[] buf = barr.toByteArray();
            String Base64String = Base64.encodeToString(buf, Base64.DEFAULT);

            SharedPreferences pre = context.getSharedPreferences(SP_NETWORKWATCH, Context.MODE_PRIVATE);
            SharedPreferences.Editor edit = pre.edit();
            edit.putString("NetworkWatch", Base64String);
            edit.commit();

        }
        catch (Exception e)
        {}
    }

    private static DateItem todayItem()
    {
        Calendar c = Calendar.getInstance();
        // int year = c.get(Calendar.YEAR);
        // int month = c.get(Calendar.MONTH) + (1-Calendar.JANUARY);
        // int day = c.get(Calendar.DAY_OF_MONTH);

        SimpleDateFormat datesdf = new SimpleDateFormat("M月d日", Locale.getDefault());
        String date = datesdf.format(c.getTime());

        for (DateItem item : datas)
        {
            // if(item.year == year && item.month == month && item.day == day)
            if (item.date.equals(date))
            {
                return item;
            }
        }

        DateItem todayItem = new DateItem();
        todayItem.date = date;
        // todayItem.year = year;
        // todayItem.month = month;
        // todayItem.day = day;

        for (int i = 0; i < datas.length - 1; i++)
        {
            datas[i] = datas[i + 1];
        }

        datas[datas.length - 1] = todayItem;

        return todayItem;
    }

    public static DateItem[] getNetDate()
    {
        return datas;
    }

    public static class DateItem
    {
        public long appAll = 0;
        public long appGprs = 0;
        public long appWifi = 0;

        public long systemAll = 0;
        public long systemGprs = 0;
        public long systemWifi = 0;

        // public int year, month, day;
        public String date = "undefine";

        public DateItem()
        {}

        public void Save(DataOutputStream don)
        {
            try
            {
                don.writeLong(appAll);
                don.writeLong(appGprs);
                don.writeLong(appWifi);

                don.writeLong(systemAll);
                don.writeLong(systemGprs);
                don.writeLong(systemWifi);

                // don.writeInt(year);
                // don.writeInt(month);
                // don.writeInt(day);
                don.writeUTF(date);

            }
            catch (Exception e)
            {}
        }

        public void Load(DataInputStream din)
        {
            try
            {
                appAll = din.readLong();
                appGprs = din.readLong();
                appWifi = din.readLong();

                systemAll = din.readLong();
                systemGprs = din.readLong();
                systemWifi = din.readLong();

                // year = din.readInt();
                // month = din.readInt();
                // day = din.readInt();
                date = din.readUTF();

            }
            catch (Exception e)
            {}
        }
    }
}
